package com.game.jumper.bean;

import java.math.BigDecimal;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;

import android.R.bool;

import com.game.jumper.game.Constant;

/**
 * 板子对象定义类
 * 
 * @author houjibo
 */
public class Board
{
	/**
	 * 布尔数组
	 */
	private static final boolean[] BOOLEAN_ARRAY = new boolean[] { false, true };

	/**
	 * 当前屏幕上的最后一个板子
	 */
	private static Board lastBoard = null;

	/**
	 * 板子的ID
	 */
	private long boardID;

	/**
	 * 板子的高度（距离屏幕上方的距离）
	 */
	private double hight;

	/**
	 * 板子的宽度（距离屏幕左侧的距离）
	 */
	private double width;

	/**
	 * 板子的厚度
	 */
	private double thick;

	/**
	 * 板子是否在屏幕的左侧
	 */
	private boolean left;

	/**
	 * 板子是否处于激活状态
	 */
	private boolean active;

	/**
	 * 板子是否处于恢复状态
	 */
	private boolean recover;

	/**
	 * 板子弯曲时差分的点坐标集合 Map<X坐标，Y坐标>
	 */
	private Map<Double, Double> locations = new TreeMap<Double, Double>();

	/**
	 * 板子是否为死亡状态
	 */
	private boolean dead = false;

	double d, d1;

	/**
	 * 
	 */
	boolean recok;

	/**
	 * 构造方法
	 * 
	 * @param hight
	 * @param width
	 * @param thick
	 */
	public Board(double hight, double width, double thick)
	{
		super();
		this.hight = hight;
		this.width = width;
		this.thick = thick;
		this.left = true;
		this.active = false;
		initLocations();
		lastBoard = this;
	}

	/**
	 * 判断板子是否死亡
	 * 
	 * @return
	 */
	public boolean isDead()
	{
		return dead;
	}

	/**
	 * 按照时间周期更新板子的位置
	 * 
	 * @param ticks
	 */
	public void Update(double ticks)
	{
		// 高度随游戏速度增加，当板子移出屏幕时，设置为死亡状态
		hight += ticks * Constant.Vdown;
		if (hight >= Constant.HIGHT)
		{
			dead = true;
		}
		// 初始化当前弯曲点集合
		initLocations();
		//
		if (recok)
		{
			if (d >= 0)
			{
				d -= ticks * d1 * 3;// �ӳ�0.33��ָ�
				setback(d);
			}
			else
			{
				d = 0;
				recover = false;
				recok = false;
				initLocations();
			}
		}
	}

	public void SetD(double d)
	{
		this.d = d;
		d1 = d;
		recok = true;
		setback(d);
	}

	void setback(double d)
	{
		getLocations().clear();
		if (isLeft())
		{
			for (int i = 0; i <= getWidth(); i += 10)
			{
				addLocation(i, d * Math.pow(i * 1.0 / getWidth(), 2) + getHight());
			}
		}
		else
		{
			for (int i = 0; i <= getWidth(); i += 10)
			{
				addLocation(Constant.Width - i, d * Math.pow(i * 1.0 / getWidth(), 2) + getHight());
			}
		}
	}

	public double getHight()
	{
		return hight;
	}

	public double getWidth()
	{
		return width;
	}

	public double getThick()
	{
		return thick;
	}

	public boolean isLeft()
	{
		return left;
	}

	public void setHight(double hight)
	{
		this.hight = hight;
	}

	public void setHight(int hight)
	{
		this.hight = hight;
	}

	public void setThick(int thick)
	{
		this.thick = thick;
	}

	public void setLeft(boolean left)
	{
		this.left = left;
	}

	public boolean isActive()
	{
		return active;
	}

	public void setActive(boolean active)
	{
		this.active = active;
	}

	public long getBoardID()
	{
		return boardID;
	}

	public void setBoardID(long boardID)
	{
		this.boardID = boardID;
	}

	public void setLocations(Map<Double, Double> locations)
	{
		this.locations = new TreeMap<Double, Double>(locations);
	}

	public Map<Double, Double> getLocations()
	{
		synchronized (locations)
		{
			return locations;
		}
	}

	public void initLocations()
	{
		synchronized (locations)
		{
			locations.clear();
			if (left)
			{
				addLocation(0, hight);
				addLocation(width, hight);
			}
			else
			{
				addLocation(Constant.Width - width, hight);
				addLocation(Constant.Width, hight);
			}
		}
	}

	public void addLocation(double x, double y)
	{
		synchronized (locations)
		{
			locations.put(x, y);
		}
	}

	public boolean isRecover()
	{
		return recover;
	}

	@Override
	public String toString()
	{
		return "Board [boardID=" + boardID + ", hight=" + hight + ", width=" + width + ", thick=" + thick + ", left="
				+ left + ", active=" + active + "]";
	}

	public void setRecover(boolean recover)
	{
		this.recover = recover;
	}

	public static Board nextBoard()
	{
		Board nextBoard = null;
		if (lastBoard != null)
		{
			if (lastBoard.isLeft())
			{
				nextBoard = getNextBoarFromLeft(lastBoard);
			}
			else
			{
				nextBoard = getNextBoarFromRight(lastBoard);
			}
		}
		if (nextBoard != null)
		{
			lastBoard = nextBoard;
			nextBoard.initLocations();
		}
		return nextBoard;
	}

	private static Board getNextBoarFromLeft(Board preBoard)
	{
		Board nextBoard = null;
		double preW = preBoard.getWidth();
		double preT = preBoard.getThick();
		double rightMaxX = Constant.Width - 12 * Constant.Unit;
		double rightMinX = preW + 6 * Constant.Unit;
		double leftMaxX = preW - 6 * Constant.Unit;
		double leftMinX = 12 * Constant.Unit;
		double nextW = 0;
		Random random = new Random();
		boolean nextIsLeft = false;
		if (rightMaxX > rightMinX && leftMaxX <= leftMinX)
		{
			nextIsLeft = false;
		}
		if (rightMaxX <= rightMinX && leftMaxX > leftMinX)
		{
			nextIsLeft = true;
		}
		if (rightMaxX > rightMinX && leftMaxX > leftMinX)
		{
			nextIsLeft = BOOLEAN_ARRAY[random.nextInt(Integer.MAX_VALUE) % 2];
		}
		if (rightMaxX <= rightMinX && leftMaxX <= leftMinX)
		{
			throw new IllegalArgumentException("Get next board width error!");
		}
		if (nextIsLeft)
		{
			nextW = ((random.nextInt(9) + 1) / 10.0) * (leftMaxX - leftMinX) + leftMinX;
		}
		else
		{
			nextW = Constant.Width - (((random.nextInt(9) + 1) / 10.0) * (rightMaxX - rightMinX)) - rightMinX;
		}
		nextW = new BigDecimal(nextW).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
		nextBoard = new Board(0, nextW, preT);
		nextBoard.setLeft(nextIsLeft);
		return nextBoard;
	}

	private static Board getNextBoarFromRight(Board preBoard)
	{
		Board nextBoard = null;
		double preW = preBoard.getWidth();
		double preT = preBoard.getThick();
		double leftMinX = 12 * Constant.Unit;
		double leftMaxX = Constant.Width - preW - 6 * Constant.Unit;

		double rightMaxX = Constant.Width - 12 * Constant.Unit;
		double rightMinX = Constant.Width - preW + 6 * Constant.Unit;
		double nextW = 0;
		Random random = new Random();
		boolean nextIsLeft = false;
		if (rightMaxX > rightMinX && leftMaxX <= leftMinX)
		{
			nextIsLeft = false;
		}
		if (rightMaxX <= rightMinX && leftMaxX > leftMinX)
		{
			nextIsLeft = true;
		}
		if (rightMaxX > rightMinX && leftMaxX > leftMinX)
		{
			nextIsLeft = BOOLEAN_ARRAY[random.nextInt(Integer.MAX_VALUE) % 2];
		}
		if (rightMaxX <= rightMinX && leftMaxX <= leftMinX)
		{
			throw new IllegalArgumentException("Get next board width error!");
		}
		if (nextIsLeft)
		{
			nextW = ((random.nextInt(Integer.MAX_VALUE) % 10 + 1) / 10.0) * (leftMaxX - leftMinX) + leftMinX;
		}
		else
		{
			nextW = Constant.Width - (((random.nextInt(Integer.MAX_VALUE) % 10 + 1) / 10.0) * (rightMaxX - rightMinX))
					- rightMinX;
		}
		nextW = new BigDecimal(nextW).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
		nextBoard = new Board(0, nextW, preT);
		nextBoard.setLeft(nextIsLeft);
		return nextBoard;
	}
}
